//==============================================================================
//
//               Copyright (C) 2004  Dick van Oudheusden
//  
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//==============================================================================
// 
//  $Date: 2007-10-30 21:17:43 $ $Revision: 1.6 $
//
//==============================================================================

#include <stdlib.h>
#include <unistd.h>

#include "ofc/config.h"

#include "ofc/DTCPServer.h"
#include "ofc/DTCPClient.h"
#include "ofc/DTimer.h"

#include "DTest.h"

#ifdef WIN32
#define WITH_THREADS
#endif

//-Wrapper---------------------------------------------------------------------

@interface TestServer : DTCPServer
{
}

- start :(id <DSocketAddressable>) address;
- (BOOL) handleRequest :(DData *) request :(DData *) response;

@end


@implementation TestServer

//----------------------------------------------------------------------------

- start :(id <DSocketAddressable>) address
{
#ifdef WITH_THREADS
  [self start :address :5 :DTS_THREADING :1];
  
  [DTimer delay :300];

  objc_thread_exit();
#else
  int child = fork();

  if (child == 0)
  {
    [self start :address :5 :DTS_THREADING :1];
  
    [DTimer delay :300];

    exit(0);
  }
#endif
  return self;
}

- (BOOL) handleRequest :(DData *) request :(DData *) response
{
  long value      = 0;
  BOOL shouldStop = NO;

  value = [request readLong];
  
  value++; // return the long increased by one
  
  if (value == 0)
    shouldStop = YES;
  
  [response writeLong :value];
  
  return shouldStop;
}

@end

//----------------------------------------------------------------------------

void DTcpServerClient_test()
{
  DInetSocketAddress *address1  = [DInetSocketAddress new];
  DInetSocketAddress *address2  = [DInetSocketAddress new];
  
  DData              *send      = [DData new];
  DData              *receive   = nil;
  
  TestServer         *server    = [TestServer new];
  DTCPClient         *client    = [DTCPClient new];

  DSocket            *socket    = nil;
  
  STARTTEST();

  [address1 any :7000];

  TEST([server open :[address1 family] :[DSocket protocol :"tcp"]]);

#ifdef WITH_THREADS
  if (objc_thread_detach(@selector(start:), server, address1) == NULL)
  {
    printf("Could not start thread\n");
  }
#else
  [server start :address1];
#endif

  [DTimer delay :200];
  
  [address2 loopback :7000];
  
  TEST([client open :[address2 family] :[DSocket protocol :"tcp"]]);
  
  TEST([client start :address2]);
  
  socket = [client socket];
  
  [send writeLong :8];
  
  receive = [client doRequest :[send data] :[send length] :50];
  
  TEST(receive != nil);

  TEST([receive readLong] == 9);
  
  [receive free];
  
  [send clear];
  
  [send writeLong :90];
  
  receive = [client doRequest :[send data] :[send length] :50];
  
  TEST(receive != nil);

  TEST([receive readLong] == 91);
  
  [receive free];

  [send clear];
  [send writeLong :0]; // the server will stop
  
  receive = [client doRequest :[send data] :[send length] :50];
  
  TEST(receive != nil);

  TEST([receive readLong] == 1);
  
  [receive free];
  
  [client stop];
  
  [send free];
  
  [server free];
  [client free];
  
  [address2 free];  
  [address1 free];
  
  STOPTEST();
}

